#ifndef __DEDUP_MEM_DOT_H__
#define __DEDUP_MEM_DOT_H__
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#include <vector>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#define __USE_BIMAP__
#ifdef  __USE_BIMAP__
#include <boost/bimap.hpp>
using namespace boost;
//#define __USE_USO__
#ifdef  __USE_USO__
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;
#else
#include <map>
#endif
#else
#include <map>
#endif
#include <HashFunctions.h>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#include <Statistics.h>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
template < typename node_t > class DedupMem {
private:
   
   static const U32 maxPathLen = 60;
   node_t zeroNode;
   
   U32 virtNodes[ maxPathLen ]; // total virtual node count (path expanded)
   U32 vpceNodes[ maxPathLen ]; // virtual nodes, path compacted
   // -- overcounts the uniqe path expanded nodes -- U32 upcxNodes[ maxPathLen ]; // unique nodes, (path expanded)
   U32 uniqNodes[ maxPathLen ]; // unique nodes
public:
   const U32 deg;
   
   std::vector< U32 > freeList;
   #ifdef __USE_BIMAP__
   #ifdef __USE_USO__
   bimap< bimaps::unordered_set_of< node_t >, bimaps::unordered_set_of< U32 > > ddmMap;
   #else
   bimap< node_t, U32 > ddmMap;
   #endif
   #else
   #ifdef __USE_USO__
   unordered_map< node_t, U32 > fwdMap;
   unordered_map< U32, node_t > bakMap;
   #else
   std::map< node_t, U32 > fwdMap;
   std::map< U32, node_t > bakMap;
   #endif
   #endif
   
   #ifdef __USE_USO__
   unordered_map< U32, U32 >    refCow;
   #else
   std::map< U32, U32 >         refCow;
   #endif
   
   DedupMem( const U32 _deg );
   void Audit( void ) const;
   void SerializeNodes( std::vector< node_t > & nodes ) const;
   void TransferStats( DagStatistics & dagStats, const U32 hgt );
   void DecRC   ( const node_t & node );
   U32  Alloc   ( const node_t & node );
   U32  Lookup  ( const node_t & node );
   U32  Lookup  ( const node_t & node, const U32 lvl );
   inline void DeAlloc ( const node_t & node, const U32 plid ) {
      
      // -- ?? not necessary, hurts performance?? -- refCow.erase( plid );
      #ifdef __USE_BIMAP__
      ddmMap.right.erase( plid );
      #else
      bakMap.erase( plid );
      fwdMap.erase( node );
      #endif
      
      freeList.push_back( plid );
   }
   inline void IncRC   ( const U32 plid ) {
      refCow[ plid ] += 1;
   }
   node_t pread( const U32 plid ) const;
};
#endif
